package com.jiyinit.web.core.common.util;

import com.jiyinit.core.framework.base.util.LogUtil;
import com.jiyinit.web.core.common.config.PropertyPlaceholderConfigurer;
import com.jiyinit.web.core.common.token.Token;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by lr on 2018/2/9.
 */
public class HttpClientUtil {
    private static final String GET  = "GET";
    private static final String POST = "POST";
    private static final String CHARSET = "UTF-8";

    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientUtil.class);

    private HttpClientUtil(){

    }

    /**
     * 创建HTTP连接
     * @param url 连接地址
     * @param method 连接打开方式
     * @param headers 请求头信息
     * @return
     */
    private static HttpURLConnection getHttpConnection(String url,String method, Map<String, String> headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        LogUtil.info(LOGGER, "http请求:{}", url);
        URL _url = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)_url.openConnection();

        conn.setRequestMethod(method);
        conn.setDoOutput(true);
        conn.setDoInput(true);

        //设置超时时间
        conn.setConnectTimeout(60*1000);
        conn.setReadTimeout(60*1000);

        //设置请求头
//        conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
//        conn.setRequestProperty("Content-Type","application/json");
        conn.setRequestProperty("accept","application/json");
//        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");

        if (headers != null && !headers.isEmpty())
            for (Map.Entry<String, String> entry : headers.entrySet())
                conn.setRequestProperty(entry.getKey(), entry.getValue());
        return conn;
    }

    /**
     * POST方式请求。
     */
    public static String get(String url,  Map<String, String> params, Map<String, String> headers) {
        LogUtil.info(LOGGER, "http以{}方式向{}发送请求","get", url);
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        try {
            conn = getHttpConnection(buildUrlWithQueryString(url,params), GET, headers);
            conn.connect();
            return readResponseString(conn);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }
    /**
     * POST方式请求。
     */
    public static String post(String url, String params, Map<String, String> headers) {
        LogUtil.info(LOGGER, "http以{}方式向{}发送请求","post", url);
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        try {
            conn = getHttpConnection(url, POST, headers);
            conn.setUseCaches(false);
            conn.addRequestProperty("request_json","{}");

            PrintWriter pw = new PrintWriter(conn.getOutputStream());
            pw.print("request_json="+params);
            pw.flush();
            pw.close();
//            conn.connect();
            return readResponseString(conn);

        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }
/**
 * 功能描述:去哪儿对接发送http post请求
 * @auther: WUSM
 * @date: 2018/12/22 9:17
 */
    public static String doPost(String url, String params,String Tag) {

        Map<String, String> param = new HashMap();
        //生成签名 并组装系统级参数和应用级参数
        param = Token.getQunarSign(Tag, params);
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8");
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            LogUtil.info(LOGGER, "resultString:{}", resultString);
        } catch (Exception e) {
            LogUtil.error(LOGGER, "do request error:{}", e);
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return resultString;
    }

    /**
     * 构造请求地址字符串
     * @param url
     * @param queryParas
     * @return
     */
    private static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
        if (queryParas == null || queryParas.isEmpty())
            return url;

        StringBuilder sb = new StringBuilder(url);
        boolean isFirst;
        if (url.indexOf("?") == -1) {
            isFirst = true;
            sb.append("?");
        }
        else {
            isFirst = false;
        }

        for (Map.Entry<String, String> entry : queryParas.entrySet()) {
            if (isFirst) isFirst = false;
            else sb.append("&");

            String key = entry.getKey();
            String value = entry.getValue();
            if (value!=null && value.trim().length()>0)
                try {value = URLEncoder.encode(value, CHARSET);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}
            sb.append(key).append("=").append(value);
        }
        return sb.toString();
    }

    /**
     * 读取请求结果，并封装为String类型
     * @param conn
     * @return
     */
    private static String readResponseString(HttpURLConnection conn) {

        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        try {
            int requestCode = conn.getResponseCode();
            inputStream = conn.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, CHARSET));
            String line = null;
            while ((line = reader.readLine()) != null){
                sb.append(line);
            }
            LogUtil.info(LOGGER, "服务器返回：{}",URLDecoder.decode(sb.toString(),"utf-8"));
            LogUtil.info(LOGGER, "服务器返回：{}",new String(sb.toString().getBytes("iso-8859-1"),"utf-8"));
            LogUtil.info(LOGGER, "服务器返回：{}",new String(sb.toString().getBytes("gbk"),"utf-8"));
            LogUtil.info(LOGGER, "服务器返回：{}",new String(sb.toString().getBytes("utf-8"),"utf-8"));
            LogUtil.info(LOGGER, "服务器返回：{}", sb.toString());
            return sb.toString();
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
